Перейти к основному содержимому

Микросервисы 2

· 3 мин. чтения

В прошлой статье я начал изучать микросервисный подход, но до полноценного решения тогда не дошёл. Тогда я пробовал сам поднимать процессы на php, управлять ими, связывать между собой через очереди потому что монолит не мог справиться с асинхронными задачами. Но чего у меня реально нехватало, так это нормальной изоляции и деплоймента, межсервисного взаимодействия и стабильной работы.

Docker

Я сразу скажу что не знаю как настраивать production с докер-контейнерами, но сервисы в рабочем окружении поднимаются тривиально

Концепции

Images (образы) это изолированная среда, как правило с конкретным языком (node, php) или библиотекой. За это отвечает Dockerfile, который ссылается на существующий, скачиваемый образ на докер хабе.

Что-бы увидеть установленные образы, есть комманда  docker images . 

Контейнеры  это запущенные образы которые изолированы от host-машины. Обычно контейнер поднимается для какого-то сервиса, поэтому у него есть своё название, явно объявлен маппинг сетевых портов на host-машину и способ монтирования файловой системы -  за это отвечает docker-compose.yml

Что-бы увидеть установленные образы, есть комманда  docker images . 

Контейнеры  это запущенные образы которые изолированы от host-машины. Обычно контейнер поднимается для какого-то сервиса, поэтому у него есть своё название, явно объявлен маппинг сетевых портов на host-машину и способ монтирования файловой системы -  за это отвечает docker-compose.yml

По умолчанию порт  не перебрасываются на такой же , а файлы хоста не линкуются и  не будут обновляться внутри контейнера  после старта.

Что-бы увидеть запущенные контейнеры, есть комманда  docker ps  (а лучше dry)

Что-бы запустить текущую папку есть  docker-compose down && docker-compose up  — это основная комманда которой вы будете пользоваться в разработке если будете делать изменения

Для автоматизации перезагрузки контейнера при изменении файлов на hostе, для node надо копать в сторону pm2-docker

Consul

Консул это сервер, который служит для связывания сервисов воедино (service discovery), поддержания их состояния здоровья (healthcheck) и для их конфигурации без перезапуска (key-value storage)

Каждый поднимающийся сервис сам должен зарегистрировать себя в консуле, указать на каком IP/порте он работает. Сам должен открыть HTTP endpoint который будет выдавать состояние здоровья

Сложности

При создании микросервисов самая сложная часть это граница и управление.  Сервис должен отвечать за конкретную бизнес-функцию и доменную область. Это вертикальный срез приложения.  Но при этом сервис должен выполнять весь стек работы — ui, backend, db storage, queue processor. Впихивать столько ответсвенности в один сервис технологически сложно, поэтому приходится дробить вертикальный стек ещё на несколько горизонтальных слоёв. Образно был article-manager - стал article-frontend, article-server, article-worker, над которыми нависают ещё всякие сервисы мониторинга. Это тяжело связывать вместе и деплоить разом.

Node

Поскольку нода висит постоянно в памяти, в отличие от php, который запускается при запросе, то возникает проблема перезагрузки кода при его изменении. Вот как выглядит Dockerfile с PM2:

FROM node:6-alpine
USER root
ENV PORT=3000
EXPOSE 3000
RUN npm install pm2 -g
WORKDIR /app
CMD ["pm2-docker", "start", "pm2.json", "--watch"]

Теперь в pm2.json описывается при каком случае надо перезапускать докер сервис

{
"apps": [
{
"name": "article-manager",
"script": "index.js",
"env": {
"PORT": 3000,
"CONSUL_IP": "192.168.10.10",
"CONSUL_PORT": 8500,
"SERVICE_NAME": "article-manager"
},
"watch": true,
"ignore_watch": [
"node_modules",
"npm-debug.log",
".idea",
".git",
"test/coverage"
],
"watch_options": {
"followSymlinks": false
}
}
]
}

Redis

Очень быстрая in-memory база для кеширования данных

version: '2'
services:
redis-master:
image: 'redis:2.8'
network_mode: bridge
volumes:
- ./data:/data
ports:
- 6379:6379
command: redis-server --appendonly yes

Alias

Для удобства, советую добавить в ваш ~/.bashrc или ~/.zshrc алиас на быстрое поднятие контейнера:

alias doc='docker-compose down && docker-compose up'